package org.springframework.boot.autoconfigure.netty;

import io.netty.util.NettyRuntime;
import io.netty.util.internal.SystemPropertyUtil;
import org.springframework.boot.autoconfigure.netty.enums.StartUpMode;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * Author: huoxingzhi
 * Date: 2020/12/10
 * Email: hxz_798561819@163.com
 */

@ConfigurationProperties(prefix = "spring.netty")
public class NettyProperties {

    private static int defaultProductConsumerThreadCount = SystemPropertyUtil.getInt(
            "io.netty.eventLoopThreads",
            NettyRuntime.availableProcessors());

    private long consumerStartTimeout = 6000;

    private int serverPort = 8888;

    private int messageMapCapacity = (int) Math.ceil(defaultProductConsumerThreadCount / 2);

    private int bossGroupLoopThreads = 1;

    private int workGroupLoopThreads = defaultProductConsumerThreadCount;

    private int messageQueueCapatity = 1000;

    private long consumerThreadSleep = 500L;

    private Long messageQueueTimeout = 500L;

    private int consumerProcessThreadCorePoolSize = 10;

    private int consumerProcessThreadPoolMaxPoolSize = 100;

    private int consumerProcessThreadPoolQueueCapacity = 10;

    private String protoBufBasePackage = "";

    private StartUpMode startUpMode = StartUpMode.SERVER;

    private String serverIpAddress = "localhost";

    private int maxFramePayloadLength = 1024*64;

    private boolean useWebSocketCompression = false;

    private String[] arguementResolverBasePackages = new String[]{};

    private String[] httpEndPointBasePackages = new String[]{};

    private int allowClientTimeOutCount = 3;

    private int channelOptionConnectTimeoutMillis = 6000;
    /**
     * ChannelOption.SO_BACKLOG对应的是tcp/ip协议listen函数中的backlog参数，函数listen(int socketfd,int backlog)用来初始化服务端可连接队列，服务端处理客户端连接请求是顺序处理的，所以同一时间只能处理一个客户端连接，多个客户端来的时候，服务端将不能处理的客户端连接请求放在队列中等待处理，backlog参数指定了队列的大小
     */
    private int channelOptionSoBacklog = 1000;


    /**
     * ChannelOption.TCP_NODELAY参数对应于套接字选项中的TCP_NODELAY,该参数的使用与Nagle算法有关,Nagle算法是将小的数据包组装为更大的帧然后进行发送，而不是输入一次发送一次,因此在数据包不足的时候会等待其他数据的到了，组装成大的数据包进行发送，虽然该方式有效提高网络的有效负载，但是却造成了延时，而该参数的作用就是禁止使用Nagle算法，使用于小数据即时传输，于TCP_NODELAY相对应的是TCP_CORK，该选项是需要等到发送的数据量最大的时候，一次性发送数据，适用于文件传输。
     */
    private boolean channelOptionTcpNodelay = true;

    /**
     *  Channeloption.SO_KEEPALIVE参数对应于套接字选项中的SO_KEEPALIVE，该参数用于设置TCP连接，当设置该选项以后，连接会测试链接的状态，这个选项用于可能长时间没有数据交流的连接。当设置该选项以后，如果在两小时内没有数据的通信时，TCP会自动发送一个活动探测数据报文。
     */
    private boolean channelOptionSoKeepalive = true;

    /**
     * ChannelOption.SO_LINGER参数对应于套接字选项中的SO_LINGER,Linux内核默认的处理方式是当用户调用close（）方法的时候，函数返回，在可能的情况下，尽量发送数据，不一定保证会发生剩余的数据，造成了数据的不确定性，使用SO_LINGER可以阻塞close()的调用时间，直到数据完全发送
     */
    private int channelOptionSoLinger = 6000;

    /**
     * 一个连接的远端关闭时本地端是否关闭，默认值为False。值为False时，连接自动关闭；为True时，触发ChannelInboundHandler的userEventTriggered()方法，事件为ChannelInputShutdownEvent。
     */
    private boolean channelOptionAllowHalfClosure = false;

    private String viewPrefix = "static";

    private String viewSuffix = ".html";

    public long getConsumerStartTimeout() {
        return consumerStartTimeout;
    }

    public void setConsumerStartTimeout(long consumerStartTimeout) {
        this.consumerStartTimeout = consumerStartTimeout;
    }

    public int getServerPort() {
        return serverPort;
    }

    public void setServerPort(int serverPort) {
        this.serverPort = serverPort;
    }

    public int getMessageMapCapacity() {
        return messageMapCapacity;
    }

    public void setMessageMapCapacity(int messageMapCapacity) {
        this.messageMapCapacity = messageMapCapacity;
    }

    public int getBossGroupLoopThreads() {
        return bossGroupLoopThreads;
    }

    public void setBossGroupLoopThreads(int bossGroupLoopThreads) {
        this.bossGroupLoopThreads = bossGroupLoopThreads;
    }

    public int getWorkGroupLoopThreads() {
        return workGroupLoopThreads;
    }

    public void setWorkGroupLoopThreads(int workGroupLoopThreads) {
        this.workGroupLoopThreads = workGroupLoopThreads;
    }

    public int getMessageQueueCapatity() {
        return messageQueueCapatity;
    }

    public void setMessageQueueCapatity(int messageQueueCapatity) {
        this.messageQueueCapatity = messageQueueCapatity;
    }

    public long getConsumerThreadSleep() {
        return consumerThreadSleep;
    }

    public void setConsumerThreadSleep(long consumerThreadSleep) {
        this.consumerThreadSleep = consumerThreadSleep;
    }

    public Long getMessageQueueTimeout() {
        return messageQueueTimeout;
    }

    public void setMessageQueueTimeout(Long messageQueueTimeout) {
        this.messageQueueTimeout = messageQueueTimeout;
    }

    public int getConsumerProcessThreadCorePoolSize() {
        return consumerProcessThreadCorePoolSize;
    }

    public void setConsumerProcessThreadCorePoolSize(int consumerProcessThreadCorePoolSize) {
        this.consumerProcessThreadCorePoolSize = consumerProcessThreadCorePoolSize;
    }

    public int getConsumerProcessThreadPoolMaxPoolSize() {
        return consumerProcessThreadPoolMaxPoolSize;
    }

    public void setConsumerProcessThreadPoolMaxPoolSize(int consumerProcessThreadPoolMaxPoolSize) {
        this.consumerProcessThreadPoolMaxPoolSize = consumerProcessThreadPoolMaxPoolSize;
    }

    public int getConsumerProcessThreadPoolQueueCapacity() {
        return consumerProcessThreadPoolQueueCapacity;
    }

    public void setConsumerProcessThreadPoolQueueCapacity(int consumerProcessThreadPoolQueueCapacity) {
        this.consumerProcessThreadPoolQueueCapacity = consumerProcessThreadPoolQueueCapacity;
    }

    public String getProtoBufBasePackage() {
        return protoBufBasePackage;
    }

    public void setProtoBufBasePackage(String protoBufBasePackage) {
        this.protoBufBasePackage = protoBufBasePackage;
    }

    public StartUpMode getStartUpMode() {
        return startUpMode;
    }

    public void setStartUpMode(StartUpMode startUpMode) {
        this.startUpMode = startUpMode;
    }

    public String getServerIpAddress() {
        return serverIpAddress;
    }

    public void setServerIpAddress(String serverIpAddress) {
        this.serverIpAddress = serverIpAddress;
    }

    public int getMaxFramePayloadLength() {
        return maxFramePayloadLength;
    }

    public void setMaxFramePayloadLength(int maxFramePayloadLength) {
        this.maxFramePayloadLength = maxFramePayloadLength;
    }

    public boolean isUseWebSocketCompression() {
        return useWebSocketCompression;
    }

    public void setUseWebSocketCompression(boolean useWebSocketCompression) {
        this.useWebSocketCompression = useWebSocketCompression;
    }

    public String[] getArguementResolverBasePackages() {
        return arguementResolverBasePackages;
    }

    public void setArguementResolverBasePackages(String[] arguementResolverBasePackages) {
        this.arguementResolverBasePackages = arguementResolverBasePackages;
    }

    public String[] getHttpEndPointBasePackages() {
        return httpEndPointBasePackages;
    }

    public void setHttpEndPointBasePackages(String[] httpEndPointBasePackages) {
        this.httpEndPointBasePackages = httpEndPointBasePackages;
    }

    public boolean isChannelOptionSoKeepalive() {
        return channelOptionSoKeepalive;
    }

    public int getAllowClientTimeOutCount() {
        return allowClientTimeOutCount;
    }

    public void setAllowClientTimeOutCount(int allowClientTimeOutCount) {
        this.allowClientTimeOutCount = allowClientTimeOutCount;
    }

    public int getChannelOptionConnectTimeoutMillis() {
        return channelOptionConnectTimeoutMillis;
    }

    public void setChannelOptionConnectTimeoutMillis(int channelOptionConnectTimeoutMillis) {
        this.channelOptionConnectTimeoutMillis = channelOptionConnectTimeoutMillis;
    }

    public int getChannelOptionSoBacklog() {
        return channelOptionSoBacklog;
    }

    public void setChannelOptionSoBacklog(int channelOptionSoBacklog) {
        this.channelOptionSoBacklog = channelOptionSoBacklog;
    }

    public boolean isChannelOptionTcpNodelay() {
        return channelOptionTcpNodelay;
    }

    public void setChannelOptionTcpNodelay(boolean channelOptionTcpNodelay) {
        this.channelOptionTcpNodelay = channelOptionTcpNodelay;
    }

    public boolean getChannelOptionSoKeepalive() {
        return channelOptionSoKeepalive;
    }

    public void setChannelOptionSoKeepalive(boolean channelOptionSoKeepalive) {
        this.channelOptionSoKeepalive = channelOptionSoKeepalive;
    }

    public int getChannelOptionSoLinger() {
        return channelOptionSoLinger;
    }

    public void setChannelOptionSoLinger(int channelOptionSoLinger) {
        this.channelOptionSoLinger = channelOptionSoLinger;
    }

    public boolean isChannelOptionAllowHalfClosure() {
        return channelOptionAllowHalfClosure;
    }

    public void setChannelOptionAllowHalfClosure(boolean channelOptionAllowHalfClosure) {
        this.channelOptionAllowHalfClosure = channelOptionAllowHalfClosure;
    }

    public String getViewPrefix() {
        return viewPrefix;
    }

    public void setViewPrefix(String viewPrefix) {
        this.viewPrefix = viewPrefix;
    }

    public String getViewSuffix() {
        return viewSuffix;
    }

    public void setViewSuffix(String viewSuffix) {
        this.viewSuffix = viewSuffix;
    }
}
